{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Routed Sequencing with Cleanup Memory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This model extends the routed sequencing model by creating a scalar ensemble 'cleanup' as explained in the book. You will project the 'state' on to the 'cleanup' ensemble using a transformation matrix 'pd', specified by the vocabulary vector 'A'. This implies that each component of the state vector (i.e., the cortical element) is multiplied by the corresponding component of the 'A' vector and summed to produce a one dimensional quantity represented by the 'cleanup' ensemble. This operation is similar to the dot product of the state vector and the vocabulary vector 'A'."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Setup for the notebook\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "\n",
    "import nengo\n",
    "from nengo import spa\n",
    "from nengo.spa import Vocabulary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create the Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This model has parameters as described in the book, with a one dimensional cleanup ensemble consisting of 100 neurons."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Number of dimensions for the Semantic Pointers\n",
    "dimensions = 16\n",
    "\n",
    "# Make a model object with the SPA network\n",
    "model = spa.SPA(label='Routed_Sequence with cleanupA', seed=12)\n",
    "\n",
    "with model:\n",
    "    # Specifying the modules to be used\n",
    "    model.state = spa.State(dimensions=dimensions, feedback=1, feedback_synapse=0.01)\n",
    "    model.vision = spa.State(dimensions=dimensions) \n",
    "    \n",
    "    # Specify the action mapping\n",
    "    actions = spa.Actions(\n",
    "        'dot(vision, START) --> state = vision',\n",
    "        'dot(state, A) --> state = B',\n",
    "        'dot(state, B) --> state = C',\n",
    "        'dot(state, C) --> state = D',\n",
    "        'dot(state, D) --> state = E',\n",
    "        'dot(state, E) --> state = A'\n",
    "    )\n",
    "    \n",
    "    # Creating the BG and Thalamus components that confirm to the specified rules\n",
    "    model.BG = spa.BasalGanglia(actions=actions)\n",
    "    model.thal = spa.Thalamus(model.BG)\n",
    "    \n",
    "    # Change the seed of this RNG to change the vocabulary\n",
    "    rng = np.random.RandomState(0)\n",
    "    vocab = Vocabulary(dimensions=dimensions)\n",
    "\n",
    "    # Create the transformation matrix (pd) and the cleanup ensemble (cleanupA) \n",
    "    pd = [vocab['A'].v.tolist()] \n",
    "    model.cleanup = spa.State(neurons_per_dimension=100, dimensions=1)\n",
    "    \n",
    "    # Function that provides the model with an initial input semantic pointer.\n",
    "    def start(t):\n",
    "        if t < 0.4:\n",
    "            return '0.8*START+D'\n",
    "        else:\n",
    "            return '0'\n",
    "\n",
    "    # Input\n",
    "    model.input = spa.Input(vision=start)\n",
    "    \n",
    "    # Projecting the state of the cortex on to the cleanup ensemble using a transformation matrix 'pd'.\n",
    "    nengo.Connection(model.state.output, model.cleanup.input, transform=pd)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run the Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Import the nengo_gui visualizer to run and visualize the model.\n",
    "from nengo_gui.ipython import IPythonViz\n",
    "IPythonViz(model, \"ch7-spa-sequence-routed-cleanup.py.cfg\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Press the play button in the visualizer to run the simulation. You should see the graphs as shown in the figure below.\n",
    "\n",
    "The graph on the bottom-left shows the semantic pointer representation of the values stored in the `state` and the response of the `cleanup` population is shown in the graph on the bottom-right. The graph on the top-right shows the utility (similarity) of the current basal ganglia input (i.e., `state`) with the possible vocabulary vectors. Since the cleanup operation is similar to a dot product between the state of the cortical element (`state`) and the defined vocabulary vector 'A', the value of the `cleanup` population rises only when the `state` (top-right graph) is 'A'. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from IPython.display import Image\n",
    "Image(filename='ch7-spa-sequence-routed-cleanup.png')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
